package pt.compflow.client.api;

import org.json.JSONObject;
import org.restlet.data.CookieSetting;
import org.restlet.data.Status;
import org.restlet.representation.EmptyRepresentation;
import org.restlet.representation.Representation;
import org.restlet.resource.Post;
import org.restlet.resource.Put;

import pt.compflow.Context;
import pt.compflow.Instantiator;
import pt.compflow.InstantiatorImpl;
import pt.compflow.client.BaseResource;
import pt.compflow.client.EngineApplication;
import pt.compflow.client.EngineApplicationListener;
import pt.compflow.flowontology.model.FLOWO;
import pt.compflow.flowontology.model.FlowOntologyModel;
import pt.compflow.flowontology.model.InternalGroupMembership;
import pt.compflow.flowontology.model.Person;
import pt.compflow.flowontology.model.PersonGroup;
import pt.compflow.storage.TripleStoreConnection;
import pt.ipp.isep.gecad.o2c.model.impl.DateContainer;
import pt.ipp.isep.gecad.o2c.model.impl.DateContainer.DateContainerType;

import com.hp.hpl.jena.util.iterator.ExtendedIterator;

public class AuthResource extends APIBaseResource {

//	private static final Logger LOG = LoggerFactory.getLogger(PersonResource.class);

	@Post("json")
	public Representation auth(String json) {
		getCookieSettings().clear();	
		getCookieSettings().add(new CookieSetting(0, "k", null, "/", null));
		getCookieSettings().add(new CookieSetting(0, "p", null, "/", null));
						
		JSONObject request = new JSONObject(json);
		
		if(!request.has("key")) {
			setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
			return new EmptyRepresentation();
		}
		
		String key = request.getString("key");

		Context context = getCompFlowContext();
		TripleStoreConnection store = context.getStoreConnection();
		store.openStore();
		
		FlowOntologyModel model = store.connectModel();
				
		Person person = getPerson(model, key);

		if (person == null) {
			setStatus(Status.CLIENT_ERROR_NOT_FOUND);
			store.closeStore();
			return new EmptyRepresentation();
		} 
				
		getCookieSettings().add(new CookieSetting(0, "k", key, "/", null));
		getCookieSettings().add(new CookieSetting(0, "p", person.getURI(), "/", null));
		
		store.closeStore();
		
		setStatus(Status.SUCCESS_OK);
		return new EmptyRepresentation();
	}
	
	@Put("json")
	public Representation register(String json) {
		
		JSONObject request = new JSONObject(json);
		
		if(!request.has("firstName") || !request.has("lastName") || !request.has("email") || !request.has("key") || !request.has("groupUri") ||
				request.getString("firstName").length() <= 1 || request.getString("lastName").length() <= 1 || request.getString("email").length() <= 4 || request.getString("groupUri").length() <= 4) {
			setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
			return new EmptyRepresentation();
		}
		
		Context context = getCompFlowContext();
		TripleStoreConnection store = context.getStoreConnection();
		store.openStore();
		
		FlowOntologyModel model = store.connectModel();
		
		String groupUri = request.getString("groupUri");
		if(groupUri.compareToIgnoreCase(BaseResource.ADMIN_LOCAL_GROUP_URI) == 0 || model.getPersonGroupWithURI(groupUri) == null) {
			setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
			store.closeStore();
			return new EmptyRepresentation();
		}
		
		ExtendedIterator<InternalGroupMembership> it = model.listInternalGroupMemberships(null, null, null, null, request.getString("email"), null);
		if(it.hasNext()) {
			setStatus(Status.CLIENT_ERROR_CONFLICT);
			store.closeStore();
			return new EmptyRepresentation();
		}
				
		Instantiator inst = new InstantiatorImpl();
		Person p = model.createPersonWithURI(FLOWO.getURI() + inst.getUniqueId("person", model));
		p.setHasFirstName(request.getString("firstName"), null);
		p.setHasLastName(request.getString("lastName"), null);
		p.setHasEmail(request.getString("email"), null);
		p.setRegistryTime(new DateContainer(DateContainerType.DATETIME));
		
		// first person registering is admin
		if(!model.listInternalGroupMemberships().hasNext()) {
			PersonGroup adminGroup = model.createPersonGroupWithURI(ADMIN_LOCAL_GROUP_URI);
			InternalGroupMembership membership = model.createInternalGroupMembershipWithURI(FLOWO.getURI() + inst.getUniqueId("membership", model));
			membership.setHasGroupPersonGroup(adminGroup);
			membership.setHasPersonPerson(p);
			membership.setHasKey(request.getString("key"), null);
			membership.setHasUsername(request.getString("email"), null);
			
			p.addHasMembershipPersonGroupMembership(membership);
			adminGroup.addHasMembershipPersonGroupMembership(membership);
		}
		
		PersonGroup group = model.getPersonGroupWithURI(groupUri);
		InternalGroupMembership membership = model.createInternalGroupMembershipWithURI(FLOWO.getURI() + inst.getUniqueId("membership", model));
		membership.setHasGroupPersonGroup(group);
		membership.setHasPersonPerson(p);
		membership.setHasKey(request.getString("key"), null);
		membership.setHasUsername(request.getString("email"), null);
		
		p.addHasMembershipPersonGroupMembership(membership);
		group.addHasMembershipPersonGroupMembership(membership);
		
		for(EngineApplicationListener l : ((EngineApplication) getApplication()).getEngineApplicationListeners()) {
			l.onPersonRegistered(model, p);
		}
		
		getCookieSettings().clear();	
		getCookieSettings().add(new CookieSetting(0, "k", request.getString("key"), "/", null));
		getCookieSettings().add(new CookieSetting(0, "p", p.getURI(), "/", null));
		
		store.closeStore();
		
		setStatus(Status.SUCCESS_OK);
		return new EmptyRepresentation();
	}
}
